package org.wisdom.data.jpa.repository;

import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.repository.NoRepositoryBean;
import org.springframework.data.repository.query.FluentQuery;
import org.springframework.lang.Nullable;
import org.wisdom.data.jpa.entity.ObjectEntity;

import java.io.Serializable;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Function;

/**
 * 仓储基础接口
 * 
 * @author zhangzhiyan
 * @date 2022/04/15 12:56
 **/
@SuppressWarnings("NullableProblems")
@NoRepositoryBean
public interface WisdomRepository<T extends ObjectEntity, K extends Serializable>
    extends JpaRepository<T, K>, JpaSpecificationExecutor<T> {

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:42
     * @param entity
     *            实体
     * @return S 实体
     */
    @Override
    <S extends T> S save(S entity);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:43
     * @param entities
     *            实体
     * @return java.util.List<S> list
     */
    @Override
    <S extends T> List<S> saveAll(Iterable<S> entities);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:43
     * @param entities
     *            实体
     * @return java.util.List<S> list
     */
    @Override
    <S extends T> List<S> saveAllAndFlush(Iterable<S> entities);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:44
     * @param entity
     *            实体
     * @return S s
     */
    @Override
    <S extends T> S saveAndFlush(S entity);

    /**
     * 重写
     *
     * @author 张智研
     * @date 2022/06/09 14:47
     * @return java.util.List<T>
     */
    @Override
    List<T> findAll();

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:48
     * @param sort
     *            sort
     * @return java.util.List<T>
     */
    @Override
    List<T> findAll(Sort sort);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:48
     * @param ids
     *            ids
     * @return java.util.List<T>
     */
    @Override
    List<T> findAllById(Iterable<K> ids);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:48
     */
    @Override
    void flush();

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:48
     * @param entities
     *            entities
     */
    @Override
    void deleteAllInBatch(Iterable<T> entities);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:49
     * @param ids
     *            ids
     */
    @Override
    void deleteAllByIdInBatch(Iterable<K> ids);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:49
     */
    @Override
    void deleteAllInBatch();

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:49
     * @param id
     *            id
     * @return T t
     */
    @Override
    T getById(K id);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:51
     * @param example
     *            example
     * @return java.util.List<S> list
     */
    @Override
    <S extends T> List<S> findAll(Example<S> example);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:52
     * @param example
     *            example
     * @param sort
     *            sort
     * @return java.util.List<S>
     */
    @Override
    <S extends T> List<S> findAll(Example<S> example, Sort sort);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:52
     * @param spec
     *            spec
     * @return java.util.Optional<T>
     */
    @Override
    Optional<T> findOne(@Nullable Specification<T> spec);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:52
     * @param spec
     *            spec
     * @return java.util.List<T>
     */
    @Override
    List<T> findAll(@Nullable Specification<T> spec);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:52
     * @param spec
     *            spec
     * @param pageable
     *            pageable
     * @return org.springframework.data.domain.Page<T>
     */
    @Override
    Page<T> findAll(@Nullable Specification<T> spec, Pageable pageable);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:53
     * @param spec
     *            spec
     * @param sort
     *            sort
     * @return java.util.List<T>
     */
    @Override
    List<T> findAll(@Nullable Specification<T> spec, Sort sort);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:53
     * @param spec
     *            spec
     * @return long
     */
    @Override
    long count(@Nullable Specification<T> spec);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:53
     * @param pageable
     *            pageable
     * @return org.springframework.data.domain.Page<T>
     */
    @Override
    Page<T> findAll(Pageable pageable);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:53
     * @param id
     *            id
     * @return java.util.Optional<T>
     */
    @Override
    Optional<T> findById(K id);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:53
     * @param id
     *            id
     * @return boolean
     */
    @Override
    boolean existsById(K id);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:53
     * @return long
     */
    @Override
    long count();

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:54
     * @param id
     *            id
     */
    @Override
    void deleteById(K id);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:54
     * @param entity
     *            entity
     */
    @Override
    void delete(T entity);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:54
     * @param ids
     *            ids
     */
    @Override
    void deleteAllById(Iterable<? extends K> ids);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:54
     * @param entities
     *            entities
     */
    @Override
    void deleteAll(Iterable<? extends T> entities);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:54
     */
    @Override
    void deleteAll();

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:55
     * @param example
     *            example
     * @return java.util.Optional<S>
     */
    @Override
    <S extends T> Optional<S> findOne(Example<S> example);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:55
     * @param example
     *            example
     * @param pageable
     *            pageable
     * @return org.springframework.data.domain.Page<S>
     */
    @Override
    <S extends T> Page<S> findAll(Example<S> example, Pageable pageable);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:55
     * @param example
     *            example
     * @return long
     */
    @Override
    <S extends T> long count(Example<S> example);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:55
     * @param example
     *            example
     * @return boolean
     */
    @Override
    <S extends T> boolean exists(Example<S> example);

    /**
     * 重写
     * 
     * @author 张智研
     * @date 2022/06/09 14:55
     * @param example
     *            example
     * @param queryFunction
     *            queryFunction
     * @return R
     */
    @Override
    <S extends T, R> R findBy(Example<S> example, Function<FluentQuery.FetchableFluentQuery<S>, R> queryFunction);

    /**
     * 逻辑删除
     * 
     * @author zhangzhiyan
     * @date 2022/04/15 13:55
     * @param id
     *            主键
     */
    void logicalDeleteById(K id);

    /**
     * 执行修改语句
     * 
     * @param jpql
     *            jpql语句
     * @param params
     *            参数
     * @return 是否成功
     */
    int executeUpdate(String jpql, Object... params);

    /**
     * 执行修改语句
     * 
     * @param jpql
     *            jpql语句
     * @param params
     *            参数
     * @return 是否成功
     */
    int executeUpdate(String jpql, Map<String, Object> params);
}